package crcache

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/go-redis/redis"
	"longmen/server/config/global"
	"longmen/server/internal/rpc/tencentim/imsdk"
	messages2 "longmen/server/internal/rpc/tencentim/messages"
	"longmen/server/internal/rpc/tencentim/messages/sports"
	"sync"
	"time"
)

type (
	LineUpItem struct {
		ID           int         `json:"id"`                  // 球员id
		TeamID       int         `json:"team_id"`             // 球队id
		First        int         `json:"first"`               // 是否首发，1-是、0-否
		Captain      int         `json:"captain"`             // 是否队长，1-是、0-否
		Name         string      `json:"name"`                // 球员名称
		Logo         string      `json:"logo"`                // 球员logo
		NationalLogo string      `json:"national_logo"`       // 球员logo(国家队)
		ShirtNumber  int         `json:"shirt_number"`        // 球衣号
		Position     string      `json:"position"`            // 球员位置，F前锋、M中场、D后卫、G守门员、其他为未知
		X            int         `json:"x"`                   // 阵容x坐标，总共100
		Y            int         `json:"y"`                   // 阵容y坐标，总共100
		Rating       string      `json:"rating"`              // 评分，10为满分
		Incidents    []Incidents `json:"incidents,omitempty"` // 球员事件列表，有事件存在，默认不存在
	}
	Player struct {
		ID   int    `json:"id"`   // 球员id
		Name string `json:"name"` // 中文名称
	}
	Incidents struct {
		Type       int    `json:"type"`        // 事件类型，详见状态码->技术统计
		Time       string `json:"time"`        // 事件发生时间（含加时时间，'A+B':A-比赛时间,B-加时时间）
		Belong     int    `json:"belong"`      // 发生方，0-中立、1-主队、2-客队
		HomeScore  int    `json:"home_score"`  // 主队比分
		AwayScore  int    `json:"away_score"`  // 客队比分
		ReasonType int    `json:"reason_type"` // 红黄牌、换人事件原因，详见状态码->事件原因（红黄牌、换人事件存在）
		Player     Player `json:"player"`      // player-相关球员
		Assist1    Player `json:"assist1"`     // assist1-助攻球员1
		Assist2    Player `json:"assist2"`     // assist1-助攻球员2
		InPlayer   Player `json:"in_player"`   // in_player-换上球员
		OutPlayer  Player `json:"out_player"`  // out_player-换下球员
	}
	LineUp struct {
		MatchId       int          `json:"match_id"`       // 赛程ID
		Confirmed     int          `json:"confirmed"`      // 正式阵容，1-是、0-不是
		HomeFormation string       `json:"home_formation"` // 主队阵型 3-4-3
		AwayFormation string       `json:"away_formation"` // 客队阵型 4-4-1-1
		Home          []LineUpItem `json:"home"`           // 阵容信息
		Away          []LineUpItem `json:"away"`           // 阵容信息
	}

	TimeLineItem struct {
		// TODO: 暂时 不需要
	}

	CricketLineupCustom struct {
		// TODO: 暂时 不需要
	}
)

type LineUpCache struct {
	rds redis.UniversalClient
}

var lineupCache *LineUpCache
var lineupCacheOnce sync.Once

const (
	CacheExpire              = time.Hour * 24 * 7 //保留7天
	CricketBallIndexCacheKey = "match_live:cricket_lineup:"
	CricketBallIndexName     = "cricket_lineup"
)

func NewLineUpRedis() *LineUpCache {
	lineupCacheOnce.Do(func() {
		lineupCache = &LineUpCache{
			rds: global.GetRds(),
		}
	})
	return lineupCache
}

// 生成板球阵容Key
func (l *LineUpCache) genLineUpKey(matchId int) string {
	return fmt.Sprintf("%s%d", CricketBallIndexCacheKey, matchId)
}
func (l *LineUpCache) PublishLineup(data LineUp) error {
	message := sports.CricketLineupMessage{
		SentMessageStruct: messages2.SentMessageStruct{Type: messages2.LineupMessageType},
		Lineup:            data,
	}

	marshal, _ := json.Marshal(message)
	err := l.rds.Set(l.genLineUpKey(data.MatchId), string(marshal), CacheExpire).Err()
	if err != nil {
		global.Log.Error("set cache err", err)
	}
	l.cutBroadcast(data.MatchId, string(marshal))
	return nil
}

// cutBroadcast 分批次推送
func (l *LineUpCache) cutBroadcast(matchId int, msg string) {
	sLen := len(msg)
	split := 3 //和客户端约定分成三段

	for i := 0; i < split; i++ {
		var lineupRsp sports.LineupResp
		lineupRsp.Type = fmt.Sprint("lineupLive-", i+1)
		if i == 2 {
			lineupRsp.Lineup = msg[i*sLen/split:]
		} else {
			lineupRsp.Lineup = msg[i*sLen/split : (i+1)*sLen/split]
		}
		m, err := json.Marshal(lineupRsp)
		if err != nil {
			global.Log.Errorf("cricket linup marshal err : %v, room_id : %v", err, matchId)
		}

		global.Log.Debugf("cricket send : %+v", string(m))
		imsdk.GetSdk().Broadcast(matchId, []string{string(m)})
	}
}

// GetLineUpCache 获取缓存
func (l *LineUpCache) GetLineUpCache(matchId int) string {
	result, err := l.rds.Get(l.genLineUpKey(matchId)).Result()
	if err != nil {
		return ""
	}
	return result
}

//WriteToEs 写进es
func (l *LineUpCache) WriteToEs(cacheKey string) bool {
	ttl, err := l.rds.TTL(cacheKey).Result()
	if err != nil {
		global.Log.Errorf("err:%v", err)
		return false
	}
	global.Log.Errorf("ttl:%v", err)
	if ttl.Seconds() > 3600 {
		return false
	}
	result, err := l.rds.Get(cacheKey).Result()
	if err != nil {
		global.Log.Errorf("err:%v", err)
		return false
	}
	_, err = global.GetEs().Index().Index(CricketBallIndexName).BodyJson(result).Do(context.Background())
	if err != nil {
		global.Log.Errorf("err:%v", err)
		return false
	}
	err = l.rds.Del(cacheKey).Err()
	if err != nil {
		global.Log.Errorf("err:%v", err)
	}
	return true
}

func (l *LineUpCache) GetAllLineUp() []string {
	r, err := l.rds.Keys(CricketBallIndexCacheKey + "*").Result()
	if err != nil {
		global.Log.Errorf("err:%v", err)
		return []string{}
	}
	return r
}
